﻿#ifndef PCRSTATE_H
#define PCRSTATE_H

#define FAILURE_VALUE "nan"

#include <QString>
#include <QList>
#include <QVector>
#include <QMap>
#include <QSet>
#include <QPointF>
#include <QWidget>
#include <QDomDocument>
#include <QSqlDatabase>
#include <QDate>
#include <QMessageBox>
#include <QTableWidget>
#include <QDir>
#include <QTimer>
#include <QElapsedTimer>

#include "dbHelper.h"
#include "xlsxdocument.h"
#include "qpcrModel.h"
#include "logHelperJ.h"


typedef int CURVE;
typedef int POSI;
typedef int CHANNEL;

class PCRStateCalculator;

// 曲线唯一标识：三位数，第一位表示通道，后两位表示孔位


QString getPosiName(int posi);
int     getPosiIdx(QString name);
int     getChannelIdx(QString name);


// 全局状态数据
class PCRState
{

public:
    PCRState();
    ~PCRState();

    // 初始化-从数据库里读取数据
    void init(QString equId);

    void initExpInfo(QString expId);
    void initModelSettings();
    void initSampleInfo(QString expId);
    void initFluData(QString expId);
    void initThr();
    void initModel();

    void calculateAll();
    void calculateHalf();

    void calFilterData();
    void calModel();
    void calThreshold();
    void calCt();
    void calStandardCurve();
    void calGuideData();

    bool datao(QString outdir);

    void changeThreshold(CHANNEL channel, double value);


    void updateCurveState();

    bool checkCurve(CURVE curve);
    QMap<int, QVector<QPointF>> getStandardCurve();

public:

    // 页面状态控制  [更新: 还是把曲线选择页面和标准曲线页面区分开吧……曲线的类型会影响标曲的计算结果……]

    enum ChartType{
        RN = 0,
        DELTA_RN = 1,
        LOG_RN = 2,
        LOG_DELTA_RN = 3,
        NORM = 4,
    };

    enum PageType{
        RAW,
        AMPL,
        STANDARD,
        GUIDE,
    };

    struct stSampleInfo{
        int posi;
        QVector<bool> channel;      // 标识每个通道是否被选中
        QString name;
        QString type;
        double  conc;
        QString id;
    };

    static QVector<QString> CHANNELLIST;

    // 页面状态
    ChartType       curChart;
    PageType        curPage;
    int             guidePage;
    bool            showThr;


    // 筛选条件 key -名称  value - 是否被筛选
    QMap<POSI, bool>         posiList;
    QMap<QString, bool>      nameList;
    QMap<QString, bool>      typeList;
    QMap<CHANNEL, bool>      channelList;
    QMap<CURVE, bool>        curveList;

    // 曲线加粗
    QVector<CURVE>           boldResult;
    int                      tableSortRule = 0; // 0孔位 1样本名称 2样本类型 3荧光染料 4CT 5浓度 6平均浓度
    int                      tableSortDirect = 0; // 0正序 1或其它倒序


    // 曲线颜色
    int                      colorType = 0;         // 颜色配置 0按通道 1按样本名
    QMap<QString, QColor>    colorName;
    QMap<CHANNEL, QColor>    colorChannel;
    QMap<CURVE, QColor>      colorResult;       // 颜色存储


    // 分析配置
    int         modelFunc;
    int         modelCt;        // >=0 相对阈值  <0 相对阈值
    int         modelFilter;

    // 数据
    double                              cycleNum;
    QMap<CURVE, QVector<QPointF>>       rawData;            // 从数据库读取的原始数据 QSring=通道号+孔位号  原始数据
    QMap<CURVE, QVector<QPointF>>       rawData_filter;     // QMap<C_P, 数据列表>                      滤波后数据
    QMap<CURVE, QPCRModel::Model*>      modelList;         // 每个数据装配一个Model

    // 样本板信息
    QMap<POSI, stSampleInfo>            samplePannel;

    // 阈值参数
    QMap<CHANNEL, double>               thrList;         // QMap<Channel, 阈值>  deltaRn
    QMap<CHANNEL, double>               thrList_log;
    QMap<CHANNEL, double>               thrList_diff;   // 标准化阈值线 (无法和thrList转化)

    QMap<CHANNEL, double>               thrList_Rn;     // Rn哪来的阈值线
    QMap<CHANNEL, double>               thrList_logRn;

    QMap<CURVE, double>                 Ct;             // 根据当前阈值线获取的Ct
    QMap<CHANNEL, double>               avgCt;


    QString                             modelIR;        // 内标
    QMap<POSI, double>                  rangeIR;        // 内标孔位的曲线范围，用于标准化

    QMap<CHANNEL, double>               E;

    // 标准曲线参数
    QMap<CHANNEL, QVector<double>>      standardLine;   // 标准曲线计算结果QMap<通道名, 结果> 0-k 1-b
    QMap<CURVE, QPointF>                standardPoint;  // 标准曲线在图上的点
    QMap<CURVE, double>                 concList;       // QMap<C_P, 浓度>
    QMap<CHANNEL, double>               avgConcList;    // QMap<Channel, 浓度>

    // 指导意见参数
    QMap<POSI, double>                  ICS;
    QMap<POSI, double>                  DI;



    bool    canAnalysis = false;        // 是否能进行扩增曲线计算
    bool    canStandard = false;        // 能否进行标准曲线计算
    bool    canGuide = false;           // 是否能进行下游操作建议计算

    QString     experimentName;         // 用于导出报告
    QString     experimentRunTime;
    QString     experimentFinishTime;

    void table();
    //数据计算总浓度-抑制指数 by-cnr
    QVector<QStringList> table1Data; // 表格数据
    void datacu(int row,double famn,double vicn,double roxn,double cqv,double cqbz);

    // 指导建议-稀释 by-cnr
    QVector<QStringList> table2Data; // 表格数据
    void dataca(int row,double ICS,double DI,double AL,double AS,double Y);
    void xsui(int row,QString type,int tx);
    bool miniSTRfl=false;
    bool YSTRfl=false;

    QList<int> typeNum(); // 类型数量

    QVector<QStringList> tab2Fil(QString type);
    bool dataoGuide(QXlsx::Document& xlsx);

};

class PCRStateCalculator
{
public:
    PCRStateCalculator(PCRState* state);


private:

    PCRState*   pState;

};


#endif // PCRSTATE_H

